package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"github.com/gin-gonic/gin"
	"io"
	"log"
	"net/http"
	"strconv"
	"strings"
)

func echoDebugLog(s string) {
	if GlobalConfig.IsDebug {
		log.Println("\nDEBUG\n" + s)
	}
}

// 推送数据
func pushData(c *gin.Context, queueName string, data string) bool {
	//  推送到Redis队列
	err := pushToRedis(queueName, data)
	echoDebugLog("\nqueue : " + queueName + "\ndata : " + data)

	if err != nil {
		errStr := ""
		// 如果推送失败，保存到备份文件
		err := backupMessage(queueName, data)
		if err != nil {
			errStr = "消息推送失败，备份失败"
			c.JSON(501, gin.H{"error": errStr})
			return false
		}
		errStr = "消息推送失败，已备份"
		c.JSON(500, gin.H{"error": errStr})

		log.Println("queue: " + queueName)
		log.Println("data: " + data)
		return false
	}
	return true
}

// 通用post请求处理
func postMessage(c *gin.Context) {
	queueName := c.Param("queueName")
	var message string

	// 根据Content-Type处理不同格式的请求
	contentType := c.ContentType()

	echoDebugLog("content_type:" + contentType)

	switch {
	case strings.Contains(contentType, "application/json"):
		// 处理JSON格式
		var jsonData interface{}
		if err := c.ShouldBindJSON(&jsonData); err != nil {
			c.JSON(400, gin.H{"error": "无效的JSON格式"})
			echoDebugLog("error: 无效的JSON格式:" + err.Error())
			return
		}
		messageBytes, err := json.Marshal(jsonData)
		if err != nil {
			c.JSON(500, gin.H{"error": "消息序列化失败"})
			echoDebugLog("error: 消息序列化失败:" + err.Error())
			return
		}
		message = string(messageBytes)

	case strings.Contains(contentType, "application/x-www-form-urlencoded"):

		// 处理表单数据
		if err := c.Request.ParseForm(); err != nil {
			c.JSON(400, gin.H{"error": "解析表单数据失败"})
			echoDebugLog("error: 解析表单数据失败:" + err.Error())
			return
		}
		formData := make(map[string]interface{})
		// 处理单值字段
		for key, values := range c.Request.PostForm {
			if len(values) == 1 {
				formData[key] = values[0]
			} else {
				formData[key] = values
			}
		}
		messageBytes, err := json.Marshal(formData)
		if err != nil {
			c.JSON(500, gin.H{"error": "表单数据序列化失败"})
			echoDebugLog("error: 表单数据序列化失败:" + err.Error())
			return
		}
		message = string(messageBytes)

	case strings.Contains(contentType, "text/plain"):
		// 处理纯文本
		body, err := io.ReadAll(c.Request.Body)
		if err != nil {
			c.JSON(400, gin.H{"error": "读取请求体失败"})
			echoDebugLog("error: 读取请求体失败:" + err.Error())
			return
		}
		message = string(body)

	case strings.Contains(contentType, "multipart/form-data"):
		// 处理多部分表单数据
		form, err := c.MultipartForm()
		if err != nil {
			c.JSON(400, gin.H{"error": "解析多部分表单失败"})
			echoDebugLog("error: 解析多部分表单失败:" + err.Error())
			return
		}
		formData := make(map[string]interface{})
		// 处理表单字段
		for key, values := range form.Value {
			if len(values) > 0 {
				formData[key] = values[0]
			}
		}
		// 处理文件字段
		for key, files := range form.File {
			if len(files) > 0 {
				formData[key] = files[0].Filename
			}
		}
		messageBytes, err := json.Marshal(formData)
		if err != nil {
			c.JSON(500, gin.H{"error": "表单数据序列化失败"})
			echoDebugLog("error: 表单数据序列化失败:" + err.Error())
			return
		}
		message = string(messageBytes)

	default:
		// 处理其他内容类型
		body, err := io.ReadAll(c.Request.Body)
		if err != nil {
			c.JSON(400, gin.H{"error": "读取请求体失败"})
			echoDebugLog("error: 读取请求体失败:" + err.Error())
			return
		}
		message = string(body)
	}

	// 推送数据
	log.Println("\npost_data: " + message)
	ret := pushData(c, queueName, message)
	if !ret {
		return
	}
}

// 通用get请求处理
func getMessage(c *gin.Context) {
	queueName := c.Param("queueName")

	// 获取所有查询参数
	queryParams := make(map[string]interface{})
	for k, v := range c.Request.URL.Query() {
		if len(v) == 1 {
			queryParams[k] = v[0]
		} else {
			queryParams[k] = v
		}
	}

	// 将查询参数转换为JSON字符串
	messageBytes, err := json.Marshal(queryParams)
	if err != nil {
		c.JSON(500, gin.H{"error": "参数序列化失败"})
		return
	}

	// 推送数据
	ret := pushData(c, queueName, string(messageBytes))
	if ret == false {
		return
	}

}

// 重试失败消息
func handleRetryFailedMessages(c *gin.Context) {
	err := retryFailedMessages()
	if err != nil {
		c.JSON(503, gin.H{"code": 1, "msg": "重试任务启动失败"})
		return
	}
	c.JSON(200, gin.H{"code": 2, "status": "重试任务已启动"})
}

// 巨量spi
func handleOceanSpiMessage(c *gin.Context) {
	type BaseResponse struct {
		StatusCode    int64  `json:"StatusCode"`
		StatusMessage string `json:"StatusMessage"`
	}
	type CallbackResponse struct {
		Challenge int64 `json:"challenge"`
		BaseResp  BaseResponse
	}

	// 处理 verify 事件
	if event := c.Query("event"); event == "verify_webhook" {
		iChallenge, _ := strconv.ParseInt(c.Query("challenge"), 10, 64)
		c.JSON(http.StatusOK, CallbackResponse{
			Challenge: iChallenge,
			BaseResp:  BaseResponse{200, "ok"},
		})
		return
	}

	// 读取请求体
	body, err := c.GetRawData()
	if err != nil {
		c.JSON(http.StatusInternalServerError, CallbackResponse{
			BaseResp: BaseResponse{http.StatusInternalServerError, err.Error()},
		})
		return
	}

	// 验证签名
	signature := c.GetHeader("X-Open-Signature")
	if signature == "" {
		c.JSON(http.StatusBadRequest, CallbackResponse{
			BaseResp: BaseResponse{http.StatusBadRequest, "X-Open-Signature is null"},
		})
		return
	}
	secretKey := GlobalConfig.Server.SecretKey
	hash := hmac.New(sha256.New, []byte(secretKey))
	hash.Write(body)
	expectedSignature := hex.EncodeToString(hash.Sum(nil))
	if expectedSignature != signature {
		c.JSON(http.StatusBadRequest, CallbackResponse{
			BaseResp: BaseResponse{http.StatusBadRequest, "invalid signature"},
		})
		return
	}

	// 验签通过
	// 推送数据
	data := string(body)
	log.Println("\nocean_spi_data: " + data)
	ret := pushData(c, "ocean_spi", data)
	if ret == true {
		return
	}

	c.JSON(http.StatusOK, CallbackResponse{
		BaseResp: BaseResponse{200, "ok"},
	})
}

// 兼容不同返回格式

func handlePostMessage(c *gin.Context) {
	postMessage(c)
	c.JSON(200, gin.H{"code": 0, "msg": "success"})
}

func handleGetMessage(c *gin.Context) {
	getMessage(c)
	c.JSON(200, gin.H{"code": 0, "msg": "success"})
}

// 返回字符串 ok
func handlePostMessage2(c *gin.Context) {
	postMessage(c)
	c.String(200, "ok")
}

func handleGetMessage2(c *gin.Context) {
	getMessage(c)
	c.String(200, "ok")
}
